package org.example.chenniyrpcspingbootstarter.bootstrap;

import Config.RpcConfig;
import boot.RpcApplication;
import lombok.extern.slf4j.Slf4j;
import model.ServiceInfo;
import org.example.chenniyrpcspingbootstarter.annotation.RpcService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import register.LocalRegistry;
import register.Registry;
import register.RegistryFactory;

import java.util.Objects;

/**
 * 服务提供者启动类
 * 作用：扫描所有带有 @RpcService 注解的类，通过注解属性和反射机制获取服务信息，并完成本地及注册中心的服务注册
 */
@Slf4j
public class ProviderBootStrap implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 获取 bean 的 Class 对象
        Class<?> beanClass = bean.getClass();

        // 判断类上是否有 @RpcService 注解
        RpcService rpcService = beanClass.getAnnotation(RpcService.class);
        if (Objects.nonNull(rpcService)) {
            // 获取注解中指定的接口类型，若未指定则取第一个实现的接口
            Class<?> interfaceClass = rpcService.interfaceClass();
            if (interfaceClass == void.class) {
                // 若未指定接口类型，默认取第一个接口
                interfaceClass = beanClass.getInterfaces()[0];
            }
            String interfaceClassName = interfaceClass.getName();
            String serviceVersion = rpcService.serviceVersion();

            // 构建服务信息
            ServiceInfo serviceInfo = new ServiceInfo();

            // 本地注册中心：记录接口类名 -> 实现类对象
            LocalRegistry.registService(interfaceClassName, beanClass);

            // 获取全局配置
            RpcConfig rpcConfig = RpcApplication.getRpcConfig();
            serviceInfo.setServiceHost(rpcConfig.getServiceHost());
            serviceInfo.setServicePort(rpcConfig.getServicePort());
            serviceInfo.setServiceVersion(serviceVersion);
            serviceInfo.setServiceName(interfaceClassName);

            // 注册服务到注册中心
            Registry registry = RegistryFactory.getInstance(rpcConfig.getRegistryConfig().getRegistry());
            try {
                registry.register(serviceInfo);
            } catch (Exception e) {
                log.info("{} 注册失败", serviceInfo.getServiceKey());
            }
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
